package com.ntschy.sys.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ntschy.common.constant.Constants;
import com.ntschy.common.core.entity.dataobject.SysMenu;
import com.ntschy.common.core.entity.dataobject.SysRole;
import com.ntschy.common.core.redis.RedisCache;
import com.ntschy.sys.entity.dataobject.SysRoleMenu;
import com.ntschy.sys.mapper.SysMenuMapper;
import com.ntschy.sys.mapper.SysRoleMapper;
import com.ntschy.sys.mapper.SysRoleMenuMapper;
import com.ntschy.sys.service.ISysRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @author ezreal_geng
 */
@Service
public class SysRoleServiceImpl implements ISysRoleService {

    @Autowired
    private SysRoleMapper roleMapper;

    @Autowired
    private SysRoleMenuMapper roleMenuMapper;

    @Autowired
    private SysMenuMapper menuMapper;

    @Autowired
    private RedisCache redisCache;


    // * ================================================基础增删改查BEGIN============================================= *

    @Override
    public List<SysRole> pageRole(SysRole role) {
        return roleMapper.pageRole(role);
    }

    @Override
    public SysRole fetchRole(String roleId) {
        return roleMapper.selectById(roleId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int addRole(SysRole role) {
        role.setId(IdUtil.fastUUID());
        roleMapper.insert(role);
        return addRoleMenu(role);
    }

    @Override
    public int updateRole(SysRole role) {
        SysRole oldRole = roleMapper.selectById(role.getId());
        if(ObjectUtil.isNotNull(oldRole)) {
            String roleKey = oldRole.getRoleKey();
            roleMenuMapper.delete(new QueryWrapper<SysRoleMenu>().lambda().eq(SysRoleMenu::getRoleId, role.getId()));
            addRoleMenu(role);
            int row = roleMapper.updateById(role);
            if(row > 0) {
                redisCache.deleteObject(Constants.SYS_ROLE_BTN_KEY + roleKey);
                redisCache.deleteObject(Constants.SYS_ROLE_MENU_KEY + roleKey);
            }
            return row;
        } else {
            return 0;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteRole(String roleId) {
        SysRole role = roleMapper.selectById(roleId);
        if(ObjectUtil.isNotNull(role)) {
            String roleKey = role.getRoleKey();
            roleMenuMapper.delete(new QueryWrapper<SysRoleMenu>().lambda().eq(SysRoleMenu::getRoleId, roleId));
            int row = roleMapper.deleteById(roleId);
            if(row > 0) {
                redisCache.deleteObject(Constants.SYS_ROLE_BTN_KEY + roleKey);
                redisCache.deleteObject(Constants.SYS_ROLE_MENU_KEY + roleKey);
            }
            return row;
        } else {
            return 0;
        }

    }

    // * =================================================基础增删改查END============================================== *

    /**
     * 获取角色对应菜单[按钮]列表
     * @param roleKey 角色key
     * @return 菜单列表
     */
    @Override
    public List<SysMenu> listMenuBtnByRole(String roleKey) {
        List<SysMenu> menuBtnList = redisCache.getCacheList(Constants.SYS_ROLE_BTN_KEY + roleKey);
        if(CollectionUtil.isNotEmpty(menuBtnList)) {
            return menuBtnList;
        } else {
            List<SysMenu> menuList = menuMapper.listMenuBtnByRole(roleKey);
            if(CollectionUtil.isNotEmpty(menuList)) {
                redisCache.setCacheList(Constants.SYS_ROLE_BTN_KEY + roleKey, menuList);
                return menuList;
            } else {
                return null;
            }
        }
    }

    /**
     * 获取角色对应菜单[菜单1]列表
     * @param roleKey 角色key
     * @return 菜单列表
     */
    @Override
    public List<SysMenu> listMenuByRole(String roleKey) {
        List<SysMenu> menuBtnList = redisCache.getCacheList(Constants.SYS_ROLE_MENU_KEY + roleKey);
        if(CollectionUtil.isNotEmpty(menuBtnList)) {
            return menuBtnList;
        } else {
            List<SysMenu> menuList = menuMapper.listMenuByRole(roleKey);
            if(CollectionUtil.isNotEmpty(menuBtnList)) {
                redisCache.setCacheList(Constants.SYS_ROLE_MENU_KEY + roleKey, menuList);
                return menuList;
            } else {
                return null;
            }
        }
    }

    @Override
    public boolean checkRoleNameExist(String roleName) {
        Integer rs = roleMapper.selectCount(new QueryWrapper<SysRole>().lambda().eq(SysRole::getName, roleName));
        return rs > 0;
    }

    @Override
    public boolean checkRoleKeyExist(String roleKey) {
        Integer rs = roleMapper.selectCount(new QueryWrapper<SysRole>().lambda().eq(SysRole::getRoleKey, roleKey));
        return rs > 0;
    }

    /**
     * 新增角色菜单数据
     * @param role 角色对象
     * @return 新增结果
     */
    @Override
    public int addRoleMenu(SysRole role) {
        int rows = 1;
        // 新增用户与角色管理
        List<SysRoleMenu> list = new ArrayList<>();
        for (int i = 0; i < role.getMenuIds().length; i++) {
            SysRoleMenu rm = new SysRoleMenu();
            rm.setId(IdUtil.fastUUID());
            rm.setRoleId(role.getId());
            rm.setMenuId(role.getMenuIds()[i]);
            rm.setDataScope(role.getDataScopes()[i].getValue());
            list.add(rm);
        }
        if (list.size() > 0) {
            rows = roleMenuMapper.batchAddRoleMenu(list);
        }
        return rows;
    }

    /**
     * 根据用户ID查询权限
     */
    @Override
    public Set<String> listRolePermissionByUserId(String userId) {
        SysRole perm = roleMapper.fetchRoleByUserId(userId);
        Set<String> permsSet = new HashSet<>();
        if (ObjectUtil.isNotNull(perm)) {
            permsSet.addAll(Arrays.asList(perm.getRoleKey().trim().split(",")));
        }
        return permsSet;
    }
}
